package org.fuys.etp.core.checker.impl;

import lombok.extern.slf4j.Slf4j;
import org.fuys.etp.core.checker.EtpUpdateChecker;
import org.fuys.etp.core.model.res.TpConfigCheckResult;
import org.fuys.etp.core.model.res.TpStatusResult;
import org.fuys.etp.core.model.type.EtpTaskTrendTypeEnum;
import org.fuys.etp.core.model.type.EtpTypeEnum;
import org.fuys.etp.core.model.vo.*;
import org.springframework.stereotype.Component;

/**
 * @projectName: fuys-etp-final
 * @package: org.fuys.etp.core.checker.impl
 * @className: ThresholdChecker
 * @author: WangJing
 * @description: TODO
 * @date: 2025/2/18 22:25
 * @version: 1.0
 */
@Component
@Slf4j
public class ThresholdChecker implements EtpUpdateChecker {

    @Override
    public void checkHandle(TpRegulationStrategyVO strategy, TpStatusResult result, TpConfigCheckResult check) {
        //todo 依赖于指标收集 是不是过于耦合了？ 可能可以细分一下增长趋势？
        log.debug("Fuys etp:进行边界检查:{}",result);
        final Integer taskTrend = result.getTpStatusVO().getTaskTrend();
        if(taskTrend == null || EtpTaskTrendTypeEnum.UNABLE.getType().equals(taskTrend) ||
                EtpTaskTrendTypeEnum.UNKNOWN.getType().equals(taskTrend)){
            log.error("Fuys etp:无法获知线程池任务趋势 不进行边界检查:{}",result);
            check.setNeedChange(false);
        }
        if(EtpTaskTrendTypeEnum.NONE.getType().equals(taskTrend)){
            check.setNeedChange(false);
        }
        check.setNeedChange(true);
        if(EtpTypeEnum.STAGE_SWITCH_THREAD_POOL_EXECUTOR.type().equals(result.getPoolType())){
            if(taskTrend !=null){
                final int index = strategy.getLoadChain()
                        .indexOf(result.getConfigVO().getLoadLevel());
                final int goalIndex = taskTrend < 0 ? Math.max(index-1,0) :
                        Math.min(index+1,strategy.getLoadConfigChain().size()-1);
                check.setSuggestConfig(strategy.getLoadConfigChain()
                        .get(goalIndex));
                check.setLimitConfig(strategy.getLoadConfigChain().get(taskTrend < 0 ? Math.max(goalIndex-1,0) :
                        Math.min(goalIndex+1,strategy.getLoadConfigChain().size()-1)));
                log.debug("Fuys etp:调整此线程池:{}的阶段 上升趋势:{}",result,taskTrend);
            }
        }else if(EtpTypeEnum.ADAPTIVE_THREAD_POOLS_EXECUTOR.type().equals(result.getPoolType())){
            //调整顺序按照调整队列-> 最大线程数 -> 核心线程数
            final TpStatusVO tpStatusVO = result.getTpStatusVO();
            final TpDynamicConfigVO dynamicConfig = result.getConfigVO().getDynamicConfig();
            final TpConfigVO limitConfig = result.getLimitConfigVO();
            final TpConfigVO configVO = result.getConfigVO().copyConfig();
            final TpBaseConfigVO reportConfig = configVO.getBaseConfig();
            boolean switchLimit = false;
            if(EtpTaskTrendTypeEnum.INCREASE.getType().equals(taskTrend)){
                //如果队列还允许扩容
                if(tpStatusVO.getQueueSize() < limitConfig.getBaseConfig().getWorkQueueSize()){
                    //需要扩容 会先尝试扩容队列 如果仍然在允许的范围内 则扩容队列
                    int queue = Math.min(dynamicConfig.getMaxQueueSizeStep(),
                            (int)(tpStatusVO.getQueueSize() * tpStatusVO.getPredicted()));
                    final int workQueueSize = tpStatusVO.getQueueSize() + queue;
                    reportConfig.setWorkQueueSize(workQueueSize);
                    log.debug("Fuys etp:线程池类型:{},名称为:{} 的线程池进行队列长度增加 原大小为:{} 更改后大小为:{}",
                            result.getPoolType(),result.getPoolName(),tpStatusVO.getQueueSize(),workQueueSize);
                }else {
                    //首先尝试调整最大线程数
                    if(tpStatusVO.getMaximumPoolSize() < limitConfig.getBaseConfig().getPoolMaxSize()){
                        final int max = Math.min((int) (tpStatusVO.getPredicted() * tpStatusVO.getCorePoolSize()),
                                dynamicConfig.getMaxMaxThreadStep());
                        reportConfig.setPoolMaxSize(tpStatusVO.getMaximumPoolSize()+ max);
                        log.debug("Fuys etp:线程池类型:{},名称为:{} 的线程池进行最大线程数增加 原大小为:{} 更改后大小为:{}",
                                result.getPoolType(),result.getPoolName(),tpStatusVO.getMaximumPoolSize(),
                                tpStatusVO.getMaximumPoolSize()+ max);
                    }
                    //否则尝试调整核心线程数
                    else if(tpStatusVO.getCorePoolSize() < limitConfig.getBaseConfig().getPoolCoreSize()){
                        final int core = Math.min((int) (tpStatusVO.getPredicted() * tpStatusVO.getCorePoolSize()),
                                dynamicConfig.getMaxCoreThreadStep());
                        final int poolCoreSize = tpStatusVO.getCorePoolSize() + core;
                        reportConfig.setPoolCoreSize(poolCoreSize);
                        if(poolCoreSize>limitConfig.getBaseConfig().getPoolCoreSize()){
                            switchLimit = true;
                        }
                        log.debug("Fuys etp:线程池类型:{},名称为:{} 的线程池进行核心线程数增加 原大小为:{} 更改后大小为:{}",
                                result.getPoolType(),result.getPoolName(),tpStatusVO.getCorePoolSize(),
                                tpStatusVO.getMaximumPoolSize()+ core);
                    }
                }
            }else if(EtpTaskTrendTypeEnum.DECREASE.getType().equals(taskTrend)){
                int loadIdx = strategy.getLoadChain().
                        indexOf(Integer.valueOf(strategy.getStartLoadLevel().toString()));
                if(loadIdx == -1){
                    loadIdx = 0;
                }
                final TpConfigVO minLimit = strategy.getLoadConfigChain().get(loadIdx);
                if(tpStatusVO.getQueueSize() > limitConfig.getBaseConfig().getWorkQueueSize()){
                    int queue = Math.min(dynamicConfig.getMaxQueueSizeStep(),
                            (int)(tpStatusVO.getQueueSize() * tpStatusVO.getPredicted()));
                    reportConfig.setWorkQueueSize(Math.max(tpStatusVO.getQueueSize() - queue,
                            limitConfig.getBaseConfig().getWorkQueueSize()));
                    log.debug("Fuys etp:线程池类型:{},名称为:{} 的线程池进行队列长度减少 原大小为:{} 更改后大小为:{}",
                            result.getPoolType(),result.getPoolName(),tpStatusVO.getQueueSize(),
                            Math.max(tpStatusVO.getQueueSize() - queue,
                                    limitConfig.getBaseConfig().getWorkQueueSize()));
                }else {
                    //否则尝试调整核心线程数
                    final int core = Math.min((int) (tpStatusVO.getPredicted() * tpStatusVO.getCorePoolSize()),
                            dynamicConfig.getMaxCoreThreadStep());
                    final int max = Math.min((int) (tpStatusVO.getPredicted() * tpStatusVO.getCorePoolSize()),
                            dynamicConfig.getMaxMaxThreadStep());
                    reportConfig.setPoolCoreSize(Math.max(tpStatusVO.getCorePoolSize() - core,
                            minLimit.getBaseConfig().getPoolCoreSize()));
                    reportConfig.setPoolMaxSize(Math.max(tpStatusVO.getMaximumPoolSize()-max,
                            minLimit.getBaseConfig().getPoolMaxSize()));
                    log.debug("Fuys etp:线程池类型:{},名称为:{} 的线程池进行核心线程数减少 原大小为:{} 更改后大小为:{}",
                            result.getPoolType(),result.getPoolName(),tpStatusVO.getCorePoolSize(),
                            Math.max(tpStatusVO.getCorePoolSize() - core,
                                    minLimit.getBaseConfig().getPoolCoreSize()));
                }
            }
            if(switchLimit){
                final int goalIndex = strategy.getLoadChain()
                        .indexOf(result.getConfigVO().getFixedConfig().getFixedVersion());
                check.setLimitConfig(strategy.getLoadConfigChain().
                        get(Math.min(goalIndex+1,strategy.getLoadConfigChain().size()-1)));
            }
            check.setSuggestConfig(configVO);
        }
    }
}
